package com.seven.springcloud.service.impl;

import cn.hutool.core.util.IdUtil;
import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import com.seven.springcloud.dao.PaymentDao;
import com.seven.springcloud.entity.Payment;
import com.seven.springcloud.service.PaymentService;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PathVariable;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName PaymentServiceImpl
 * @Description paymentService 实现类
 * @Author com.seven
 * @Date 2020/4/20 14:04
 * @Version 1.0
 **/
@Service
@DefaultProperties(defaultFallback = "payment_Global_FallbackMethod")
public class PaymentServiceImpl implements PaymentService {
    @Resource
    private PaymentDao paymentDao;

    /**
     * 全局fallback
     */
    public String payment_Global_FallbackMethod(){
        return "请求服务超时了(꒦_꒦) ~请稍后重试【我是全局fallback】";
    }


    @Override
    public int create(Payment payment) {
        return paymentDao.create(payment);
    }

    @Override
    public Payment getPaymentById(Long id) {
        return paymentDao.getPaymentById(id);
    }

    @Override
    @HystrixCommand
    public String paymentInfo_OK(Integer id) {
        int i=10/0;
        return "线程池：\t"+Thread.currentThread().getName()+"payment_ok,id"
                +id+"\t(*^▽^*)";
    }

    /**
     * @HystrixCommand 服务器降级注解
     *  fallbackMethod 备胎方案
     *  commandProperties 命令属性
     *      @HystrixProperty 熔断参数
     *      这里限制3s，我们业务需要5s 所有超时了...
     * @param id
     * @return
     */
    @HystrixCommand(fallbackMethod = "paymentInfo_TimeOutHandler",commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000")
    })
    @Override
    public String paymentInfo_timeOut(Integer id) {
        int timeNumber=5;
        //休息线程timeNumber秒
        try { TimeUnit.SECONDS.sleep(timeNumber);} catch (InterruptedException e) {e.printStackTrace();}
        return "线程池：\t"+Thread.currentThread().getName()+"paymentInfo_timeOut,id"
                +id+"\t(*^▽^*)，耗时"+timeNumber+"s";
    }
    public String paymentInfo_TimeOutHandler(Integer id){
        return "o(╥﹏╥)o调用支付接口超时或异常。\t当前线程名称："+Thread.currentThread().getName();
    }

    //============服务熔断
    @HystrixCommand(fallbackMethod = "paymentCircuitBreaker_fallback",commandProperties = {
            @HystrixProperty(name = "circuitBreaker.enabled",value = "true"),//是否开启断路器
            @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"),//请求次数
            @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "10000"),//时间窗口期
            @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "60"),//失败率达到多少后跳闸
    })
    public String paymentCircuitBreaker(@PathVariable("id") Integer id){
        //自定义一个异常好测试
        if(id<0){
            throw new RuntimeException("---id 不能为负数---");
        }
        String s = IdUtil.simpleUUID();
        return Thread.currentThread().getName()+"\t调用成功,流水号："+s;
    }

    /**
     * 兜底的方法
     * @param id
     * @return
     */
    public String paymentCircuitBreaker_fallback(@PathVariable("id") Integer id){
        return "id 不能为负数,请稍后再试 o(╥﹏╥)o  id:"+id;
    }
}
